using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace System
{
    /// <summary>
    /// 时间扩展方法
    /// </summary>
    public static class DateTimeEx
    {
        //星期数组
        private static string[] _weekdays = { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };
        /// <summary>
        /// 显示简单时间
        /// <para>一天内显示时分秒，大于一天显示年月日</para>
        /// </summary>
        /// <param name="date"></param>
        /// <param name="timeformat"></param>
        /// <param name="dateformat"></param>
        /// <returns></returns>
        public static string ToSimpDate(this DateTime date, string timeformat = "HH:mm:ss", string dateformat = "yy/MM/dd")
        {
            TimeSpan ts = DateTime.Now - date;
            if (ts.TotalDays == 0)
            {
                return date.ToString(timeformat);
            }
            else
            {
                return date.ToString(dateformat);
            }
        }
        /// <summary>
        /// 显示简单时间
        /// <para>一天内显示时分秒，大于一天显示年月日</para>
        /// </summary>
        /// <param name="date"></param>
        /// <param name="timeformat"></param>
        /// <param name="dateformat"></param>
        /// <returns></returns>
        public static string ToSimpDate(this DateTime? date, string timeformat = "HH:mm:ss", string dateformat = "yy/MM/dd")
        {
            string result = "";
            if (date.HasValue)
            {
                result = date.Value.ToSimpDate(timeformat, dateformat);
            }
            return result;
        }
        /// <summary>
        /// 按格式显示时间
        /// </summary>
        /// <param name="date"></param>
        /// <param name="format"></param>
        /// <returns></returns>
        public static string ToStringByFormat(this DateTime? date, string format)
        {
            string result = "";
            if (date.HasValue)
            {
                result = date.Value.ToString(format);
            }
            return result;
        }
        /// <summary>
        /// 获得汉字星期
        /// </summary>
        public static string GetWeek(this DateTime date)
        {
            return _weekdays[(int)date.DayOfWeek];
        }
        /// <summary>
        /// 获取当天最小时间(00:00:00)
        /// <para>直接用的.Date</para>
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        public static DateTime GetDayMin(this DateTime date)
        {
            return date.Date;
        }
        /// <summary>
        /// 获取当天最大时间(23:59:59)
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        public static DateTime GetDayMax(this DateTime date)
        {
            return date.AddDays(1).AddSeconds(-1);
        }
        /// <summary>
        /// 获取月最初
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        public static DateTime GetMonthFirstDay(this DateTime date)
        {
            return new DateTime(date.Year, date.Month, 1, 0, 0, 0);
        }
        /// <summary>
        /// 获取月最末
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        public static DateTime GetMonthLastDay(this DateTime date)
        {
            var s = new DateTime(date.Year, date.Month, 1, 0, 0, 0);
            var e = s.AddMonths(1);
            return e.Date.AddSeconds(-1);
        }

        /// <summary>
        /// C#时间转换Unix时间戳
        /// </summary>
        /// <param name="time">时间</param>
        /// <param name="isLong">true 13位(毫秒) false 10位(秒)</param>
        /// <returns>Unix时间戳</returns>
        public static long ParseUnix(this System.DateTime time, bool isLong = true)
        {
            var dto = new DateTimeOffset(time);
            if (isLong)
            {
                return dto.ToUnixTimeMilliseconds();
            }
            else
            {
                return dto.ToUnixTimeSeconds();
            }
            /*
                time = TimeZoneInfo.ConvertTimeToUtc(time);
            System.DateTime startTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            long t = (time.Ticks - startTime.Ticks) / 10000; //除10000调整为13位  
            if (!isLong)
            {
                t = t / 1000;
            }
            return t;
            */
        }

        /// <summary>
        /// Unix时间戳转为C#时间
        /// </summary>
        /// <param name="timeStamp">Unix时间戳</param>
        /// <returns>C#时间</returns>
        public static DateTime ParseUnix(string timeStamp)
        {
            DateTime dtStart = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

            long lTime = long.Parse(timeStamp + (timeStamp.Length == 13 ? "0000" : "0000000"));
            TimeSpan toNow = new TimeSpan(lTime);
            var result = dtStart.Add(toNow);
            result = TimeZoneInfo.ConvertTimeFromUtc(result, TimeZoneInfo.Local);
            return result;
        }

        /// <summary>
        /// Unix时间戳转为C#时间
        /// </summary>
        /// <param name="timeStamp">Unix时间戳</param>
        /// <returns>C#时间</returns>
        public static DateTime ParseUnix(long timeStamp)
        {
            return ParseUnix(timeStamp.ToString());
        }
        /// <summary>
        /// 获取两个时间的时间差
        /// </summary>
        /// <param name="d1"></param>
        /// <param name="d2"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public static int DateDiff(this DateTime d1, DateTime d2, DateDiffMode mode = DateDiffMode.dd)
        {
            DateTime max;
            DateTime min;
            int year;
            int month;
            int tempYear, tempMonth;
            bool is_minus = false;
            if (d1 > d2)
            {
                max = d1;
                min = d2;
            }
            else
            {
                max = d2;
                min = d1;
                is_minus = true;
            }
            tempYear = max.Year;
            tempMonth = max.Month;
            if (max.Month < min.Month)
            {
                tempYear--;
                tempMonth = tempMonth + 12;
            }
            year = tempYear - min.Year;
            month = tempMonth - min.Month;
            int result = 0;
            switch (mode)
            {
                case DateDiffMode.dd:
                    TimeSpan ts = max - min;
                    result = (int)ts.TotalDays;
                    if (is_minus)
                    {
                        result = -result;
                    }
                    break;
                case DateDiffMode.mm:
                    result = month + year * 12;
                    if (is_minus)
                    {
                        result = -result;
                    }
                    break;
                case DateDiffMode.yy:
                    result = year;
                    if (is_minus)
                    {
                        result = -result;
                    }
                    break;

            }
            return result;
        }
    }
    /// <summary>
    /// 时间间隔方式
    /// </summary>
    public enum DateDiffMode
    {
        /// <summary>
        /// 年数
        /// </summary>
        yy,
        /// <summary>
        /// 月数
        /// </summary>
        mm,
        /// <summary>
        /// 天数
        /// </summary>
        dd,
    }
}
